package com.jc.order.service.impl;


import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.jc.constant.OperationTypeEnum;
import com.jc.order.common.ValidatorUtil;
import com.jc.order.dto.EciCustomerSaleApplyDTO;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Component
public class EciCustomerSaleApplyValidator {

    // 费率计算标准有效值
    private static final List<String> VALID_PAYMENTS = Arrays.asList("LC", "LCOA", "OA", "DP", "DA");

    // 保单生效日期（固定值）
//    private static final LocalDate POLICY_EFFECTIVE_DATE = LocalDate.of(2025, 6, 29);
//    保单生效日期（固定值）
    private static final DateTime POLICY_EFFECTIVE_DATE = DateUtil.parseDate("2025-06-29");
    // 信用期限起始日与出货日最大间隔天数
    private static final int MAX_DAYS_BETWEEN_START_AND_HAPPEN = 30;


    public List<String> validate(EciCustomerSaleApplyDTO dto) {
        List<String> errors = new ArrayList<>();

        //init
        dto.setCreateTime(new Date());
        dto.setUpdateUser(dto.getCreateUser());
        dto.setUpdateTime(new Date());


        // 1. 基础字段校验
        validateRequiredFields(dto, errors);

        // 2. 字段长度校验
        validateFieldLengths(dto, errors);

        // 3. 业务逻辑校验
        validateBusinessRules(dto, errors);

        // 4. 条件字段校验
        validateConditionalFields(dto, errors);


        // 5. 新增日期规则校验
        validateDateRules(dto, errors);

        return errors;
    }

    private void validateRequiredFields(EciCustomerSaleApplyDTO dto, List<String> errors) {

        if (OperationTypeEnum.MODIFY.getCode().equalsIgnoreCase(dto.getOperationType())) {
            ValidatorUtil.checkRequired(errors, dto.getCorpSerialNo(), "请求方业务流水号");
        }
        ValidatorUtil.checkRequired(errors, dto.getHappenDate(), "出货日");
        ValidatorUtil.checkRequired(errors, dto.getRiskPiccCode(), "买方picccode");
        ValidatorUtil.checkRequired(errors, dto.getStartDate(), "信用起始日");
        ValidatorUtil.checkRequired(errors, dto.getCurrency(), "币种");
        ValidatorUtil.checkRequired(errors, dto.getCountryOrArea(), "国家和地区");
        ValidatorUtil.checkRequired(errors, dto.getCustomsCode(), "海关商品代码");
        ValidatorUtil.checkRequired(errors, dto.getXamInvoiceAmout(), "赊销金额");
        ValidatorUtil.checkRequired(errors, dto.getPaymentTerms(), "信用期限");
        ValidatorUtil.checkRequired(errors, dto.getContractNo(), "发票号");
        ValidatorUtil.checkRequired(errors, dto.getContractPayment(), "费率计算标准");
//        ValidatorUtil.checkRequired(errors, dto.getExportTrade(), "商品类别");
        ValidatorUtil.checkRequired(errors, dto.getOperationType(), "操作类型");
    }

    private void validateFieldLengths(EciCustomerSaleApplyDTO dto, List<String> errors) {
        ValidatorUtil.checkMaxLength(errors, dto.getRiskPiccCode(), 22, "买方picccode");
        ValidatorUtil.checkMaxLength(errors, dto.getProductNum(), 30, "商品数量及单位");
        ValidatorUtil.checkMaxLength(errors, dto.getBankSwift(), 150, "开证行Swift码");
        ValidatorUtil.checkMaxLength(errors, dto.getCurrency(), 50, "币种");
        ValidatorUtil.checkMaxLength(errors, dto.getTransportMode(), 50, "运输方式");
        ValidatorUtil.checkMaxLength(errors, dto.getCountryOrArea(), 50, "国家和地区");
        ValidatorUtil.checkMaxLength(errors, dto.getCustomsCode(), 40, "海关商品代码");
        ValidatorUtil.checkMaxLength(errors, dto.getContractNo(), 100, "发票号");
        ValidatorUtil.checkMaxLength(errors, dto.getContractPayment(), 20, "费率计算标准");
        ValidatorUtil.checkMaxLength(errors, dto.getExportTrade(), 200, "商品类别");
        ValidatorUtil.checkMaxLength(errors, dto.getExportTradeInput(), 50, "商品类别备注");
        ValidatorUtil.checkMaxLength(errors, dto.getRemark(), 300, "备注");


    }

    private void validateBusinessRules(EciCustomerSaleApplyDTO dto, List<String> errors) {
        // 1. 费率计算标准枚举值校验（使用新的checkEnumValue方法）
        ValidatorUtil.checkEnumValue(errors, dto.getContractPayment(), VALID_PAYMENTS, "费率计算标准");

        // 2. 金额精度校验（小数点后最多两位）
        if (dto.getXamInvoiceAmout() != null && dto.getXamInvoiceAmout().scale() > 2) {
            errors.add("赊销金额最多支持两位小数");
        }
        if (dto.getXamRecoverAmount() != null && dto.getXamRecoverAmount().scale() > 2) {
            errors.add("确认收汇金额最多支持两位小数");
        }

        // 3. 信用期限范围校验（最大9999天）
        if (dto.getPaymentTerms() != null && dto.getPaymentTerms() > 9999) {
            errors.add("信用期限不能超过9999天");
        }

    }

    private void validateConditionalFields(EciCustomerSaleApplyDTO dto, List<String> errors) {
        // 1. LC/LCOA业务必填字段校验
        if (isLcBusiness(dto.getContractPayment())) {
            if (dto.getComitFormDate() == null) {
                errors.add("信用证业务必须提供提交单据日");
            }
            if (dto.getBankSwift() == null || dto.getBankSwift().isEmpty()) {
                errors.add("信用证业务必须提供开证行Swift码");
            }

            // Swift码特殊校验（不少于8位）
            if (dto.getBankSwift() != null && dto.getBankSwift().length() < 8) {
                errors.add("开证行Swift码长度不能少于8位");
            }
        }

        // 2. 商品类别备注校验（当包含"其他"时必填）
        if (dto.getExportTrade() != null && dto.getExportTrade().contains("16")) {
            if (dto.getExportTradeInput() == null || dto.getExportTradeInput().isEmpty()) {
                errors.add("商品类别包含'其他'时必须填写商品类别备注");
            }
        }

        // 3. 确认收汇金额校验（使用新的checkAmountNotExceed方法）
        if (dto.getXamRecoverAmount() != null) {
            // 检查金额是否超过赊销金额
            ValidatorUtil.checkAmountNotExceed(errors, dto.getXamRecoverAmount(),
                    dto.getXamInvoiceAmout(), "确认收汇金额");

            // 检查是否提供回款日期
            if (dto.getRecoverDate() == null) {
                errors.add("填写确认收汇金额时必须提供回款日期");
            }
        }

        // 4. 出口前标识校验
        if (dto.getIsAdditionalRisk() != null) {
            if (!"0".equals(dto.getIsAdditionalRisk()) && !"1".equals(dto.getIsAdditionalRisk())) {
                errors.add("是否为出口前值无效，必须是0或1");
            }
        }
    }


    private void validateDateRules(EciCustomerSaleApplyDTO dto, List<String> errors) {
        DateTime now = DateUtil.date();

        // 1. 出货日应在保单生效日期之后
        if (dto.getHappenDate() != null) {
            dto.setHappenDate(DateUtil.beginOfDay(dto.getHappenDate()));
            if (dto.getHappenDate().getTime() < POLICY_EFFECTIVE_DATE.getTime()) {
                errors.add("出货日(" + DateUtil.format(dto.getStartDate(), DatePattern.NORM_DATE_PATTERN) + ")不能早于保单生效日期(" + DateUtil.format(POLICY_EFFECTIVE_DATE, DatePattern.NORM_DATE_PATTERN)  + ")");
            }

            // 2. 出货日应在当前日期之前
            if (dto.getHappenDate().getTime() > now.getTime()) {
                errors.add("出货日(" + DateUtil.format(dto.getStartDate(), DatePattern.NORM_DATE_PATTERN) + ")不能晚于当前日期(" + DateUtil.format(now, DatePattern.NORM_DATE_PATTERN) + ")");
            }
        }

        // 3. 信用期限起始日应晚于出货日（可为同一天）
        if (dto.getStartDate() != null && dto.getHappenDate() != null) {
            dto.setStartDate(DateUtil.beginOfDay(dto.getStartDate()));
            if (dto.getStartDate().getTime() > dto.getHappenDate().getTime()) {
                errors.add("信用起始日(" + DateUtil.format(dto.getStartDate(), DatePattern.NORM_DATE_PATTERN) + ")不能早于出货日(" +DateUtil.format(dto.getHappenDate(), DatePattern.NORM_DATE_PATTERN)  + ")");
            }

            long betweenDay = DateUtil.between(dto.getHappenDate(), dto.getStartDate(), DateUnit.DAY);
            // 4. 信用期限起始日与出货日间隔不超过30天
            if (betweenDay > MAX_DAYS_BETWEEN_START_AND_HAPPEN) {
                errors.add("信用起始日(" +  DateUtil.format(dto.getStartDate(), DatePattern.NORM_DATE_PATTERN)   + ")与出货日(" + DateUtil.format(dto.getHappenDate(), DatePattern.NORM_DATE_PATTERN) +
                        ")间隔不能超过" + MAX_DAYS_BETWEEN_START_AND_HAPPEN + "天");
            }
        }

        // 5. 提交单据日不得早于出货日
        if (dto.getComitFormDate() != null && dto.getHappenDate() != null) {
            dto.setComitFormDate(DateUtil.beginOfDay(dto.getComitFormDate()));
            if (dto.getComitFormDate().getTime() < dto.getHappenDate().getTime()) {
                errors.add("提交单据日(" + DateUtil.format(dto.getComitFormDate(), DatePattern.NORM_DATE_PATTERN) + ")不能早于出货日(" + DateUtil.format(dto.getHappenDate(), DatePattern.NORM_DATE_PATTERN) + ")");
            }
        }
    }


    private boolean isLcBusiness(String contractPayment) {
        return contractPayment != null &&
                ("LC".equals(contractPayment) || "LCOA".equals(contractPayment));
    }
}